
/**
 * Java语言所提供的7种数值类型之间可以相互转换，有两种类型转换方式：自动类型转换和强制类型转换。
 * 编译：javac -encoding UTF-8 Conversion.java
 * 运行：java Conversion
 */
public class Conversion {
    /**
     * 自动类型转换
     * Java所有的数值型变量可以相互转换，如果系统支持把某种基本类型的值直接赋给另一种基本类型的变量，则这种方式被称为自动类型转换。
     * 当把一个表数范围小的数值或变量直接赋给另一个表数范围大的变量时，系统将可以进行自动类型转换；否则就需要强制转换。
     */
    public static void AutoConversion() {
        int a = 6;
        // int类型可以自动转换为float类型
        float f = a;
        System.out.println(f);  // 输出6.0

        byte b = 9;
        // byte类型不能自动类型转换为char类型
//        char c = b;
        // byte类型可以自动类型转换为double类型
        double d = b;
        System.out.println(d);
    }

    /**
     * 不仅如此，当把任何基本类型的值和字符串值进行连接运算时，基本类型的值将自动类型转换为字符串类型，
     * 虽然字符串类型不是基本类型，而是引用类型。
     * 因此，如果希望把基本类型的值转换为对应的字符串时，可以把基本类型的值和一个空字符串进行连接。
     */
    public static void PrimitiveAndString() {
        // 下面代码错误，5是整数，不能直接赋值给一个String类型
//        String str1 = 5;
        // 一个基本类型的值和字符串进行连接运算时，基本类型的值自动转换为字符串
        String str2 = 3.5f + "";
        System.out.println(str2);
        // 下面语句输出7Hello!
        System.out.println(3 + 4 + "Hello!");
        // 下面语句输出Hello!34
        System.out.println("Hello!" + 3 + 4);
    }

    /**
     * 强制类型转换
     * 强制类型转换的语法格式是：(targetType)value，强制类型转换的运算符是圆括号（()）
     */
    public static void NarrowConversion() {
        /*
         * 把一个浮点数强制类型转换为整数时，Java将直接截断浮点数的小数部分。
         * 把233强制类型转换为byte类型的整数，从而变成了-23，这就是典型的溢出.
         */
        int iValue = 233;
        byte bValue = (byte) iValue;
        System.out.println(bValue); // 输出-23

        double dValue = 3.98;
        int tol = (int) dValue;
        System.out.println(tol); // 输出3

        // 5.6默认是一个double类型的浮点数，因此将5.6赋值给一个float类型变量将导致错误，必须使用强制类型转换才可以
//        float a = 5.6;
        float a = (float) 5.6;

        /*
         * 在通常情况下，字符串不能直接转换为基本类型，但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。
         * 例如，把字符串转换成int类型，则可通过如下代码实现：
         */
        String str = "45";
        int iValue2 = Integer.parseInt(str);
        System.out.println(iValue2);
    }

    /**
     * 生成一个6位的随机字符串
     */
    public static void RandomStr() {
        String result = "";
        for (int i = 0; i < 6; i++) {
            // 生成一个97-122之前的int类型整数
            int intValue = (int) (Math.random() * 26 + 97);
            // 将intValue强制转换为char类型后连接到result后面
            result += (char) intValue;
        }
        System.out.println(result);
    }

    /**
     * 当一个算术表达式中包含多个基本类型的值时，整个算术表达式的数据类型将发生自动提升。
     * Java定义了如下的自动提升规则。
     * ➢ 所有的byte类型、short类型和char类型将被提升到int类型。
     * ➢ 整个算术表达式的数据类型自动提升到与表达式中最高等级操作数同样的类型。
     */
    public static void AutoPromote() {
        // 定义一个short类型的变量
        short sValue = 5;
        // 上面的“sValue-2”表达式的类型将被提升到int类型，
        // 这样就把右边的int类型值赋给左边的short类型变量，从而引起错误。
//        sValue = sValue + 2;

        byte b = 40;
        char c = 'a';
        int i = 23;
        double d = .314;
        // 右边表达式中最高等级操作数为d，double类型
        // 则右边表达式的类型为double类型，故赋值给一个double类型变量
        double result = b +c +i*d;
        System.out.println(result); // 144.222

        /*
         * 必须指出，表达式的类型将严格保持和表达式中最高等级操作数相同的类型。
         * 下面代码中两个int类型整数进行除法运算，即使无法除尽，也将得到一个int类型结果
         */
        int val = 3;
        int intResult = 23 / val;   // 右边表达式的类型为int
        System.out.println(intResult);  // 7
    }

    public static void main(String[] args) {
        AutoConversion();
        PrimitiveAndString();
        NarrowConversion();
        RandomStr();
        AutoPromote();
    }
}
